using UnityEngine;
using System.Collections.Generic;

public class Shape : PersistableObject
{
    
    Color[] colors;
    static int colorPropertyId = Shader.PropertyToID("_Color");
    static MaterialPropertyBlock sharedPropertyBlock;

    //材质
    [SerializeField]
    MeshRenderer[] meshRenderers;

    ShapeFactory originFactory;

    //追踪身上的行为组件
    List<ShapeBehavior> behaviorList = new List<ShapeBehavior>();

    void Awake()
    {
        colors = new Color[meshRenderers.Length];
    }

    //自己来管理形状的更新，unity的fixUpdate()等方法会有额外的开销
    public void GameUpdate()
    {
        //设置旋转&&速度
        for(int i = 0;i<behaviorList.Count;i++)
        {
            behaviorList[i].GameUpdate(this);
        }

    }

    int shapeId = int.MinValue;
    public int ShapeId{
        get{
            return shapeId;
        }
        set{
            if(shapeId == int.MinValue && value != int.MinValue)
                shapeId = value;
            else{
                Debug.LogError("Not allowed to change shapeId." + shapeId + " "+value);
            }
            
        }
    }

    
    public int MaterialId{//材质ID
        get;
        private set;
    }

    public void SetMaterial(Material material, int materialId)
    {//设置材质
        for(int i = 0;i<meshRenderers.Length;i++)
        {
            meshRenderers[i].material = material;
        }
        MaterialId = materialId;
    }

    public void SetColor(Color color)
    {//设置颜色
        if(sharedPropertyBlock == null){//属性块
            sharedPropertyBlock = new MaterialPropertyBlock();
        }
        
        sharedPropertyBlock.SetColor(colorPropertyId,color);
        for(int i = 0;i<meshRenderers.Length;i++)
        {
            colors[i] = color;
            meshRenderers[i].SetPropertyBlock(sharedPropertyBlock);
        }
    }

    public void SetColor(Color color, int index)
    {
        if(sharedPropertyBlock == null)
            sharedPropertyBlock = new MaterialPropertyBlock();
        
        sharedPropertyBlock.SetColor(colorPropertyId, color);
        colors[index] = color;
        meshRenderers[index].SetPropertyBlock(sharedPropertyBlock);
    }

    public int ColorCount
    {
        get{
            return colors.Length;
        }
    }

    public override void Save(GameDataWriter writer)
    {
        base.Save(writer);
        writer.Write(colors.Length);
        for(int i = 0;i<colors.Length;i++)
        {
            writer.Write(colors[i]);
        }
        writer.Write(behaviorList.Count);
        for(int i = 0;i<behaviorList.Count;i++)
        {
            writer.Write((int)behaviorList[i].BehaviorType);
            behaviorList[i].Save(writer);
        }
        
    }
    public override void Load(GameDataReader reader)
    {
        base.Load(reader);
        if(reader.Version >= 5)
        {
            LoadColor(reader);
        }else
            SetColor(reader.Version > 0 ? reader.ReadColor() : Color.white);
        
        if(reader.Version >= 6)
        {
            int behaviorCount = reader.ReadInt();
            for(int i = 0;i<behaviorCount;i++)
            {
                AddBehavior((ShapeBehaviorType)reader.ReadInt()).Load(reader);
            }
        }else if(reader.Version >= 4)
        {
            AddBehavior<RotationShapeBehavior>().AngularVelocity = reader.ReadVector3();
            AddBehavior<movementShapebehavior>().Velocity = reader.ReadVector3();
        }

    }

    private void LoadColor(GameDataReader reader)
    {
        int count = reader.ReadInt();
        int max = count <= colors.Length ? count : colors.Length;
        int i = 0;
        for(;i<max;i++)
        {
            SetColor(reader.ReadColor(), i);
        }
        if(count > colors.Length)
        {//存储的颜色超出了当前的需要，即使不使用，也必须读取
            for(;i<count;i++){
                reader.ReadColor();
            }
        }else if(count < colors.Length)
        {//存储的颜色少于当前需要的颜色
            for(;i<colors.Length;i++)
            {
                SetColor(Color.white);
            }
        }
    }

    ShapeBehavior AddBehavior(ShapeBehaviorType type)
    {
        switch(type)
        {
            case ShapeBehaviorType.Movement:
                return AddBehavior<movementShapebehavior>();
            case ShapeBehaviorType.Rotation:
                return AddBehavior<RotationShapeBehavior>();
        }
        Debug.LogError("Forgot to support " + type);
        return null;
    }

    public ShapeFactory OriginFactory
    {
        get{
            return originFactory;
        }
        set{
            if(originFactory == null)
                originFactory = value;
            else
                Debug.LogError("Not allowed to change origin factory.");
        }
    }

    public void Recycle()
    {//回收
        for(int i = 0;i<behaviorList.Count;i++)
        {
            behaviorList[i].Recycle();
        }
        behaviorList.Clear();
        OriginFactory.Reclaim(this);
    }

    //通用方法
    public T AddBehavior<T>() where  T : ShapeBehavior, new()//约束
    {
        T behavior = ShapeBehaviorPool<T>.Get();
        behaviorList.Add(behavior);
        return behavior;
    }

}